package rad.framework.hibernate;

import java.io.Serializable;
import java.util.Properties;

import rad.framework.jpa.JpaUtil;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.id.Configurable;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.IdentifierGeneratorFactory;
import org.hibernate.id.IdentityGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.type.Type;

/**
 * This can be used when you need to copy data across databases, such as an
 * authoring db and a production db, and you need to keep the ids in sync.
 * 
 * @GeneratedValue(generator="TicketIdGenerator")
 * @GenericGenerator(name="TicketIdGenerator", strategy="rad.framework.hibernate.IdentityAssignedGenerator")
 * 
 * @author boudyacho
 * 
 */
public class IdentityAssignedGenerator implements
		PostInsertIdentifierGenerator, IdentifierGenerator, Configurable {

	private IdentifierGenerator assignedGenerator;
	private IdentifierGenerator delegateGenerator;

	public Serializable generate(SessionImplementor session, Object object)
			throws HibernateException {
		Object id = JpaUtil.getIdentity((Serializable) object);
		if (id != null) {
			id = assignedGenerator.generate(session, object);
		} else {
			id = delegateGenerator.generate(session, object);
		}
		return (Serializable) id;
	}

	public void configure(Type type, Properties params, Dialect d)
			throws MappingException {
		delegateGenerator = IdentifierGeneratorFactory.create("identity", type,
				params, d);
		assignedGenerator = IdentifierGeneratorFactory.create("assigned", type,
				params, d);
	}

	public InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate(
			PostInsertIdentityPersister persister, Dialect dialect,
			boolean isGetGeneratedKeysEnabled) throws HibernateException {
		InsertGeneratedIdentifierDelegate x = ((IdentityGenerator) delegateGenerator)
				.getInsertGeneratedIdentifierDelegate(persister, dialect,
						isGetGeneratedKeysEnabled);
		return x;
	}
}